home *** CD-ROM | disk | FTP | other *** search
/ Gekikoh Dennoh Club 5 / Gekikoh Dennoh Club Vol. 5 (Japan).7z / Gekikoh Dennoh Club Vol. 5 (Japan) (Track 01).bin / internet / xip / iijppp.lzh / Drivers / BSDI-1.1 / if_tun.c < prev    next >
C/C++ Source or Header  |  1994-10-03  |  11KB  |  558 lines

  1. /*
  2.  * Copyright (c) 1988, Julian Onions <jpo@cs.nott.ac.uk>
  3.  * Nottingham University 1987.
  4.  *
  5.  * This source may be freely distributed, however I would be interested
  6.  * in any changes that are made.
  7.  *
  8.  * This driver takes packets off the IP i/f and hands them up to a
  9.  * user process to have it's wicked way with. This driver has it's
  10.  * roots in a similar driver written by Phil Cockcroft (formerly) at
  11.  * UCL. This driver is based much more on read/write/select mode of
  12.  * operation though.
  13.  * 
  14.  * $Id: if_tun.c,v 1.9 1993/12/24 03:20:59 deraadt Exp $
  15.  */
  16.  
  17. #include "tun.h"
  18. #if NTUN > 0
  19.  
  20. #include <sys/param.h>
  21. #include <sys/proc.h>
  22. #include <sys/systm.h>
  23. #include <sys/mbuf.h>
  24. #include <sys/buf.h>
  25. #include <sys/protosw.h>
  26. #include <sys/socket.h>
  27. #include <sys/ioctl.h>
  28. #include <sys/errno.h>
  29. #include <sys/syslog.h>
  30. #include <sys/select.h>
  31. #include <sys/file.h>
  32.  
  33. #include <machine/cpu.h>
  34.  
  35. #include <net/if.h>
  36. #include <net/netisr.h>
  37. #include <net/route.h>
  38.  
  39. #ifdef INET
  40. #include <netinet/in.h>
  41. #include <netinet/in_systm.h>
  42. #include <netinet/in_var.h>
  43. #include <netinet/ip.h>
  44. #include <netinet/if_ether.h>
  45. #endif
  46.  
  47. #ifdef NS
  48. #include <netns/ns.h>
  49. #include <netns/ns_if.h>
  50. #endif
  51.  
  52. #include "bpfilter.h"
  53. #if NBPFILTER > 0
  54. #include <sys/time.h>
  55. #include <net/bpf.h>
  56. #endif
  57.  
  58. #include <net/if_tun.h>
  59.  
  60. #define TUNDEBUG    if (tundebug) printf
  61. int    tundebug = 0;
  62.  
  63. struct tun_softc tunctl[NTUN];
  64. extern int ifqmaxlen;
  65.  
  66. int    tunoutput __P((struct ifnet *, struct mbuf *, struct sockaddr *));
  67. int    tunselect __P((dev_t dev, int, struct proc *));
  68. int    tunopen __P((dev_t, int, int, struct proc *));
  69. int    tunifioctl __P((struct ifnet *, int, caddr_t, int));
  70. int    tunioctl __P((dev_t, int, caddr_t, int));
  71. void    tunattach __P((int));
  72.  
  73. static int tuninit __P((int));
  74.  
  75. void
  76. tunattach(unused)
  77.     int unused;
  78. {
  79.     register int i;
  80.     struct ifnet *ifp;
  81.     struct sockaddr_in *sin;
  82.  
  83.     for (i = 0; i < NTUN; i++) {
  84.         tunctl[i].tun_flags = TUN_INITED;
  85.  
  86.         ifp = &tunctl[i].tun_if;
  87.         ifp->if_unit = i;
  88.         ifp->if_name = "tun";
  89.         ifp->if_mtu = TUNMTU;
  90.         ifp->if_ioctl = tunifioctl;
  91.         ifp->if_output = tunoutput;
  92.         ifp->if_flags = IFF_POINTOPOINT;
  93.         ifp->if_snd.ifq_maxlen = ifqmaxlen;
  94.         ifp->if_collisions = 0;
  95.         ifp->if_ierrors = 0;
  96.         ifp->if_oerrors = 0;
  97.         ifp->if_ipackets = 0;
  98.         ifp->if_opackets = 0;
  99.         if_attach(ifp);
  100. #if NBPFILTER > 0
  101.         bpfattach(&tunctl[i].tun_bpf, ifp, DLT_NULL, sizeof(u_int));
  102. #endif
  103.     }
  104. }
  105.  
  106. /*
  107.  * tunnel open - must be superuser & the device must be
  108.  * configured in
  109.  */
  110. int
  111. tunopen(dev, flag, mode, p)
  112.     dev_t    dev;
  113.     int    flag, mode;
  114.     struct proc *p;
  115. {
  116.     struct ifnet    *ifp;
  117.     struct tun_softc *tp;
  118.     register int    unit, error;
  119.  
  120.     if (error = suser(p->p_ucred, &p->p_acflag))
  121.         return (error);
  122.  
  123.     if ((unit = minor(dev)) >= NTUN)
  124.         return (ENXIO);
  125.     tp = &tunctl[unit];
  126.     if (tp->tun_flags & TUN_OPEN)
  127.         return ENXIO;
  128.     ifp = &tp->tun_if;
  129.     tp->tun_flags |= TUN_OPEN;
  130.     TUNDEBUG("%s%d: open\n", ifp->if_name, ifp->if_unit);
  131.     return (0);
  132. }
  133.  
  134. /*
  135.  * tunclose - close the device - mark i/f down & delete
  136.  * routing info
  137.  */
  138. int
  139. tunclose(dev, flag)
  140.     dev_t    dev;
  141.     int    flag;
  142. {
  143.     register int    unit = minor(dev), s;
  144.     struct tun_softc *tp = &tunctl[unit];
  145.     struct ifnet    *ifp = &tp->tun_if;
  146.     struct mbuf    *m;
  147.  
  148.     tp->tun_flags &= ~TUN_OPEN;
  149.  
  150.     /*
  151.      * junk all pending output
  152.      */
  153.     do {
  154.         s = splimp();
  155.         IF_DEQUEUE(&ifp->if_snd, m);
  156.         splx(s);
  157.         if (m)
  158.             m_freem(m);
  159.     } while (m);
  160.  
  161.     if (ifp->if_flags & IFF_UP) {
  162.         s = splimp();
  163.         if_down(ifp);
  164. #ifndef bsdi
  165.         if (ifp->if_flags & IFF_RUNNING) {
  166.             rtinit(ifp->if_addrlist, (int)RTM_DELETE,
  167.                    tp->tun_flags & TUN_DSTADDR ? RTF_HOST : 0);
  168.         }
  169. #endif
  170.         splx(s);
  171.     }
  172.     tp->tun_pgrp = 0;
  173.     selwakeup(&tp->tun_rsel);
  174.         
  175.     TUNDEBUG ("%s%d: closed\n", ifp->if_name, ifp->if_unit);
  176.     return (0);
  177. }
  178.  
  179. static int
  180. tuninit(unit)
  181.     int    unit;
  182. {
  183.     struct tun_softc *tp = &tunctl[unit];
  184.     struct ifnet    *ifp = &tp->tun_if;
  185.     register struct ifaddr *ifa;
  186.  
  187.     TUNDEBUG("%s%d: tuninit\n", ifp->if_name, ifp->if_unit);
  188.  
  189.     ifp->if_flags |= IFF_UP | IFF_RUNNING;
  190.  
  191.     for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) {
  192.         struct sockaddr_in *si;
  193.  
  194.         si = (struct sockaddr_in *)ifa->ifa_addr;
  195.         if (si && si->sin_addr.s_addr)
  196.             tp->tun_flags |= TUN_IASET;
  197.  
  198.         si = (struct sockaddr_in *)ifa->ifa_dstaddr;
  199.         if (si && si->sin_addr.s_addr)
  200.             tp->tun_flags |= TUN_DSTADDR;
  201.     }
  202.  
  203.     return 0;
  204. }
  205.  
  206. /*
  207.  * Process an ioctl request.
  208.  */
  209. int
  210. tunifioctl(ifp, cmd, data, flag)
  211.     struct ifnet *ifp;
  212.     int    cmd;
  213.     caddr_t    data;
  214.     int    flag;
  215. {
  216.     struct tun_softc *tp = &tunctl[ifp->if_unit];
  217.     int        error = 0, s;
  218.  
  219.     s = splimp();
  220.     switch(cmd) {
  221.     case SIOCSIFADDR:
  222.         tuninit(ifp->if_unit);
  223.         break;
  224.     case SIOCSIFDSTADDR:
  225.         tp->tun_flags |= TUN_DSTADDR;
  226.         TUNDEBUG("%s%d: destination address set\n", ifp->if_name,
  227.             ifp->if_unit);
  228.         break;
  229.     default:
  230.         error = EINVAL;
  231.     }
  232.     splx(s);
  233.     return (error);
  234. }
  235.  
  236. /*
  237.  * tunoutput - queue packets from higher level ready to put out.
  238.  */
  239. int
  240. tunoutput(ifp, m0, dst)
  241.     struct ifnet   *ifp;
  242.     struct mbuf    *m0;
  243.     struct sockaddr *dst;
  244. {
  245.     struct tun_softc *tp = &tunctl[ifp->if_unit];
  246.     struct proc    *p;
  247.     int        s;
  248.  
  249.     TUNDEBUG ("%s%d: tunoutput\n", ifp->if_name, ifp->if_unit);
  250.  
  251.     if ((tp->tun_flags & TUN_READY) != TUN_READY) {
  252.         TUNDEBUG ("%s%d: not ready 0%o\n", ifp->if_name,
  253.               ifp->if_unit, tp->tun_flags);
  254.         m_freem (m0);
  255.         return EHOSTDOWN;
  256.     }
  257.  
  258. #if NBPFILTER > 0
  259.     if (tp->tun_bpf) {
  260.         /*
  261.          * We need to prepend the address family as
  262.          * a four byte field.  Cons up a dummy header
  263.          * to pacify bpf.  This is safe because bpf
  264.          * will only read from the mbuf (i.e., it won't
  265.          * try to free it or keep a pointer to it).
  266.          */
  267.         struct mbuf m;
  268.         u_int af = dst->sa_family;
  269.  
  270.         m.m_next = m0;
  271.         m.m_len = 4;
  272.         m.m_data = (char *)⁡
  273.  
  274.         bpf_mtap(tp->tun_bpf, &m);
  275.     }
  276. #endif
  277.  
  278.     switch(dst->sa_family) {
  279. #ifdef INET
  280.     case AF_INET:
  281.         s = splimp();
  282.         if (IF_QFULL(&ifp->if_snd)) {
  283.             IF_DROP(&ifp->if_snd);
  284.             m_freem(m0);
  285.             splx(s);
  286.             ifp->if_collisions++;
  287.             return (ENOBUFS);
  288.         }
  289.         IF_ENQUEUE(&ifp->if_snd, m0);
  290.         splx(s);
  291.         ifp->if_opackets++;
  292.         break;
  293. #endif
  294.     default:
  295.         m_freem(m0);
  296.         return EAFNOSUPPORT;
  297.     }
  298.  
  299.     if (tp->tun_flags & TUN_RWAIT) {
  300.         tp->tun_flags &= ~TUN_RWAIT;
  301.         wakeup((caddr_t)tp);
  302.     }
  303.     if (tp->tun_flags & TUN_ASYNC && tp->tun_pgrp) {
  304.         if (tp->tun_pgrp > 0)
  305.             gsignal(tp->tun_pgrp, SIGIO);
  306.         else if (p = pfind(-tp->tun_pgrp))
  307.             psignal(p, SIGIO);
  308.     }
  309.     selwakeup(&tp->tun_rsel);
  310.     return 0;
  311. }
  312.  
  313. /*
  314.  * the cdevsw interface is now pretty minimal.
  315.  */
  316. int
  317. tunioctl(dev, cmd, data, flag)
  318.     dev_t        dev;
  319.     int        cmd;
  320.     caddr_t        data;
  321.     int        flag;
  322. {
  323.     int        unit = minor(dev), s;
  324.     struct tun_softc *tp = &tunctl[unit];
  325.     struct tuninfo *tunp;
  326.  
  327.     switch (cmd) {
  328.     case TUNSIFINFO:
  329.             tunp = (struct tuninfo *)data;
  330.         tp->tun_if.if_mtu = tunp->if_mtu;
  331.         tp->tun_if.if_type = tunp->if_type;
  332.         tp->tun_if.if_baudrate = tunp->if_baudrate;
  333.         break;
  334.     case TUNGIFINFO:
  335.         tunp = (struct tuninfo *)data;
  336.         tunp->if_mtu = tp->tun_if.if_mtu;
  337.         tunp->if_type = tp->tun_if.if_type;
  338.         tunp->if_baudrate = tp->tun_if.if_baudrate;
  339.         break;
  340.     case TUNSDEBUG:
  341.         tundebug = *(int *)data;
  342.         break;
  343.     case TUNGDEBUG:
  344.         *(int *)data = tundebug;
  345.         break;
  346.     case FIONBIO:
  347.         if (*(int *)data)
  348.             tp->tun_flags |= TUN_NBIO;
  349.         else
  350.             tp->tun_flags &= ~TUN_NBIO;
  351.         break;
  352.     case FIOASYNC:
  353.         if (*(int *)data)
  354.             tp->tun_flags |= TUN_ASYNC;
  355.         else
  356.             tp->tun_flags &= ~TUN_ASYNC;
  357.         break;
  358.     case FIONREAD:
  359.         s = splimp();
  360.         if (tp->tun_if.if_snd.ifq_head)
  361.             *(int *)data = tp->tun_if.if_snd.ifq_head->m_len;
  362.         else    
  363.             *(int *)data = 0;
  364.         splx(s);
  365.         break;
  366.     case TIOCSPGRP:
  367.         tp->tun_pgrp = *(int *)data;
  368.         break;
  369.     case TIOCGPGRP:
  370.         *(int *)data = tp->tun_pgrp;
  371.         break;
  372.     default:
  373.         return (ENOTTY);
  374.     }
  375.     return (0);
  376. }
  377.  
  378. /*
  379.  * The cdevsw read interface - reads a packet at a time, or at
  380.  * least as much of a packet as can be read.
  381.  */
  382. int
  383. tunread(dev, uio)
  384.     dev_t        dev;
  385.     struct uio    *uio;
  386. {
  387.     int        unit = minor(dev);
  388.     struct tun_softc *tp = &tunctl[unit];
  389.     struct ifnet    *ifp = &tp->tun_if;
  390.     struct mbuf    *m, *m0;
  391.     int        error=0, len, s;
  392.  
  393.     TUNDEBUG ("%s%d: read\n", ifp->if_name, ifp->if_unit);
  394.     if ((tp->tun_flags & TUN_READY) != TUN_READY) {
  395.         TUNDEBUG ("%s%d: not ready 0%o\n", ifp->if_name,
  396.               ifp->if_unit, tp->tun_flags);
  397.         return EHOSTDOWN;
  398.     }
  399.  
  400.     tp->tun_flags &= ~TUN_RWAIT;
  401.  
  402.     s = splimp();
  403.     do {
  404.         IF_DEQUEUE(&ifp->if_snd, m0);
  405.         if (m0 == 0) {
  406.             if (tp->tun_flags & TUN_NBIO) {
  407.                 splx(s);
  408.                 return EWOULDBLOCK;
  409.             }
  410.             tp->tun_flags |= TUN_RWAIT;
  411.             tsleep((caddr_t)tp, PZERO + 1, "tunread", 0);
  412.         }
  413.     } while (m0 == 0);
  414.     splx(s);
  415.  
  416.     while (m0 && uio->uio_resid > 0 && error == 0) {
  417.         len = MIN(uio->uio_resid, m0->m_len);
  418.         if (len == 0)
  419.             break;
  420.         error = uiomove(mtod(m0, caddr_t), len, uio);
  421.         MFREE(m0, m);
  422.         m0 = m;
  423.     }
  424.  
  425.     if (m0) {
  426.         TUNDEBUG("Dropping mbuf\n");
  427.         m_freem(m0);
  428.     }
  429.     return error;
  430. }
  431.  
  432. /*
  433.  * the cdevsw write interface - an atomic write is a packet - or else!
  434.  */
  435. int
  436. tunwrite(dev, uio)
  437.     dev_t        dev;
  438.     struct uio    *uio;
  439. {
  440.     int        unit = minor (dev);
  441.     struct ifnet    *ifp = &tunctl[unit].tun_if;
  442.     struct mbuf    *top, **mp, *m;
  443.     int        error=0, s, tlen, mlen;
  444.  
  445.     TUNDEBUG("%s%d: tunwrite\n", ifp->if_name, ifp->if_unit);
  446.  
  447.     if (uio->uio_resid < 0 || uio->uio_resid > TUNMTU) {
  448.         TUNDEBUG("%s%d: len=%d!\n", ifp->if_name, ifp->if_unit,
  449.             uio->uio_resid);
  450.         return EIO;
  451.     }
  452.     tlen = uio->uio_resid;
  453.  
  454.     /* get a header mbuf */
  455.     MGETHDR(m, M_DONTWAIT, MT_DATA);
  456.     if (m == NULL)
  457.         return ENOBUFS;
  458.     mlen = MHLEN;
  459.  
  460.     top = 0;
  461.     mp = ⊤
  462.     while (error == 0 && uio->uio_resid > 0) {
  463.         m->m_len = MIN (mlen, uio->uio_resid);
  464.         error = uiomove(mtod (m, caddr_t), m->m_len, uio);
  465.         *mp = m;
  466.         mp = &m->m_next;
  467.         if (uio->uio_resid > 0) {
  468.             MGET (m, M_DONTWAIT, MT_DATA);
  469.             if (m == 0) {
  470.                 error = ENOBUFS;
  471.                 break;
  472.             }
  473.             mlen = MLEN;
  474.         }
  475.     }
  476.     if (error) {
  477.         if (top)
  478.             m_freem (top);
  479.         return error;
  480.     }
  481.  
  482.     top->m_pkthdr.len = tlen;
  483.     top->m_pkthdr.rcvif = ifp;
  484.  
  485. #if NBPFILTER > 0
  486.     if (tunctl[unit].tun_bpf) {
  487.         /*
  488.          * We need to prepend the address family as
  489.          * a four byte field.  Cons up a dummy header
  490.          * to pacify bpf.  This is safe because bpf
  491.          * will only read from the mbuf (i.e., it won't
  492.          * try to free it or keep a pointer to it).
  493.          */
  494.         struct mbuf m;
  495.         u_int af = AF_INET;
  496.  
  497.         m.m_next = top;
  498.         m.m_len = 4;
  499.         m.m_data = (char *)⁡
  500.  
  501.         bpf_mtap(tunctl[unit].tun_bpf, &m);
  502.     }
  503. #endif
  504.  
  505.     s = splimp();
  506.     if (IF_QFULL (&ipintrq)) {
  507.         IF_DROP(&ipintrq);
  508.         splx(s);
  509.         ifp->if_collisions++;
  510.         m_freem(top);
  511.         return ENOBUFS;
  512.     }
  513.     IF_ENQUEUE(&ipintrq, top);
  514.     splx(s);
  515.     ifp->if_ipackets++;
  516.     schednetisr(NETISR_IP);
  517.     return error;
  518. }
  519.  
  520. /*
  521.  * tunselect - the select interface, this is only useful on reads
  522.  * really. The write detect always returns true, write never blocks
  523.  * anyway, it either accepts the packet or drops it.
  524.  */
  525. int
  526. tunselect(dev, rw, p)
  527.     dev_t        dev;
  528.     int        rw;
  529.     struct proc    *p;
  530. {
  531.     int        unit = minor(dev), s;
  532.     struct tun_softc *tp = &tunctl[unit];
  533.     struct ifnet    *ifp = &tp->tun_if;
  534.  
  535.     s = splimp();
  536.     TUNDEBUG("%s%d: tunselect\n", ifp->if_name, ifp->if_unit);
  537.  
  538.     switch (rw) {
  539.     case FREAD:
  540.         if (ifp->if_snd.ifq_len > 0) {
  541.             splx(s);
  542.             TUNDEBUG("%s%d: tunselect q=%d\n", ifp->if_name,
  543.                 ifp->if_unit, ifp->if_snd.ifq_len);
  544.             return 1;
  545.         }
  546.         selrecord(curproc, &tp->tun_rsel);
  547.         break;
  548.     case FWRITE:
  549.         splx(s);
  550.         return 1;
  551.     }
  552.     splx(s);
  553.     TUNDEBUG("%s%d: tunselect waiting\n", ifp->if_name, ifp->if_unit);
  554.     return 0;
  555. }
  556.  
  557. #endif  /* NTUN */
  558.